use axum::{
    extract::{Multipart, State},
    http::StatusCode,
    response::Json,
};
use std::sync::Arc;
use tokio::sync::Mutex;

use crate::services::tile_conversion::{TileConversionService, ConversionProgress};
use crate::utils::{AppState, file_utils};

// 全局处理状态
#[derive(Debug, Clone, Default)]
pub struct ProcessState {
    pub progress: Arc<Mutex<ConversionProgress>>,
    pub is_running: Arc<Mutex<bool>>,
}

// 转换PBF到瓦片
pub async fn convert_to_tiles(
    State(app_state): State<Arc<AppState>>,
    mut multipart: Multipart,
) -> Result<Json<serde_json::Value>, (StatusCode, String)> {
    let mut is_running = app_state.process_state.is_running.lock().await;
    if *is_running {
        return Err((StatusCode::CONFLICT, "转换任务已在进行中".to_string()));
    }
    *is_running = true;
    drop(is_running);

    // 重置进度
    let mut progress = app_state.process_state.progress.lock().await;
    *progress = ConversionProgress::default();
    drop(progress);

    // 解析请求参数
    let mut pbf_file_path = app_state.config.pbf_download_path();
    let mut min_zoom = 8;
    let mut max_zoom = 16;
    let mut include_roads = true;
    let mut include_buildings = true;
    let mut include_poi = true;
    let mut include_water = true;
    let mut include_landuse = true;
    let mut include_boundaries = true;

    while let Some(field) = multipart.next_field().await.map_err(|e| {
        (StatusCode::BAD_REQUEST, format!("解析请求失败: {}", e))
    })? {
        let name = field.name().unwrap_or("").to_string();
        match name.as_str() {
            "pbf_file" => {
                // 处理上传的文件
                let file_name = field.file_name().unwrap_or("china.osm.pbf").to_string();
                let temp_path = format!("{}/{}", app_state.config.temp_dir, file_name);
                
                match file_utils::save_uploaded_file(field, &&temp_path.as_str()).await {
                    Ok(()) => {
                        // 处理成功的情况
                        println!("文件上传保存成功");
                        // 可以添加后续操作，如记录日志、返回成功响应等
                    }
                    Err(e) => {
                        // 处理失败的情况，可根据不同错误类型进行分支处理
                        eprintln!("文件上传保存失败: {}", e);
                    }
                }
                pbf_file_path = temp_path;
            }
            "min_zoom" => {
                let value = field.text().await.map_err(|e| {
                    (StatusCode::BAD_REQUEST, format!("解析min_zoom失败: {}", e))
                })?;
                min_zoom = value.parse().map_err(|e| {
                    (StatusCode::BAD_REQUEST, format!("min_zoom必须是数字: {}", e))
                })?;
            }
            "max_zoom" => {
                let value = field.text().await.map_err(|e| {
                    (StatusCode::BAD_REQUEST, format!("解析max_zoom失败: {}", e))
                })?;
                max_zoom = value.parse().map_err(|e| {
                    (StatusCode::BAD_REQUEST, format!("max_zoom必须是数字: {}", e))
                })?;
            }
            "include_roads" => {
                let value = field.text().await.map_err(|e| {
                    (StatusCode::BAD_REQUEST, format!("解析include_roads失败: {}", e))
                })?;
                include_roads = value.parse().unwrap_or(true);
            }
            "include_buildings" => {
                let value = field.text().await.map_err(|e| {
                    (StatusCode::BAD_REQUEST, format!("解析include_buildings失败: {}", e))
                })?;
                include_buildings = value.parse().unwrap_or(true);
            }
            "include_poi" => {
                let value = field.text().await.map_err(|e| {
                    (StatusCode::BAD_REQUEST, format!("解析include_poi失败: {}", e))
                })?;
                include_poi = value.parse().unwrap_or(true);
            }
            "include_water" => {
                let value = field.text().await.map_err(|e| {
                    (StatusCode::BAD_REQUEST, format!("解析include_water失败: {}", e))
                })?;
                include_water = value.parse().unwrap_or(true);
            }
            "include_landuse" => {
                let value = field.text().await.map_err(|e| {
                    (StatusCode::BAD_REQUEST, format!("解析include_landuse失败: {}", e))
                })?;
                include_landuse = value.parse().unwrap_or(true);
            }
            "include_boundaries" => {
                let value = field.text().await.map_err(|e| {
                    (StatusCode::BAD_REQUEST, format!("解析include_boundaries失败: {}", e))
                })?;
                include_boundaries = value.parse().unwrap_or(true);
            }
            _ => {}
        }
    }

    // 验证参数
    if min_zoom < 1 || min_zoom > 18 {
        return Err((StatusCode::BAD_REQUEST, "min_zoom必须在1-18之间".to_string()));
    }
    if max_zoom < min_zoom || max_zoom > 18 {
        return Err((StatusCode::BAD_REQUEST, format!("max_zoom必须在{}-18之间", min_zoom)));
    }

    // 准备转换服务
    let conversion_service = TileConversionService::new(
        pbf_file_path,
        app_state.config.tiles_output_dir.clone(),
        min_zoom,
        max_zoom,
        include_roads,
        include_buildings,
        include_poi,
        include_water,
        include_landuse,
        include_boundaries,
        app_state.process_state.progress.clone(),
        app_state.config.max_concurrent_tasks,
    );

    let app_state_clone = app_state.clone();
    tokio::spawn(async move {
        let result = conversion_service.convert().await;
        if let Err(e) = result {
            tracing::error!("瓦片转换失败: {}", e);
        }

        // 更新运行状态
        let mut is_running = app_state_clone.process_state.is_running.lock().await;
        *is_running = false;
    });

    Ok(Json(serde_json::json!({
        "status": "success",
        "message": "转换任务已启动",
        "min_zoom": min_zoom,
        "max_zoom": max_zoom,
        "output_dir": app_state.config.tiles_output_dir
    })))
}

// 获取转换进度
pub async fn get_process_progress(
    State(app_state): State<Arc<AppState>>,
) -> Result<Json<ConversionProgress>, (StatusCode, String)> {
    let progress = app_state.process_state.progress.lock().await;
    Ok(Json(progress.clone()))
}
